
#include "NadineFramework0316/NadineFramework/NadineLibrary/Nadine09.h"
#include "MFVideoCapture.h"
#include "NDMenuDialog.h"
#include "NDLoadingScreen.h"
#include "NDAmeliaMeshForCHC.h"

#include <AR/gsub.h>
#include <AR/video.h>
#include <AR/param.h>
#include <AR/ar.h>

#include "NDMFVCTest.h"

#include "NDDAEViewer.h"


namespace Nadine
{
	NDDAEViewer* _g_NDDAEViewerPtr =0;

	//---------------------------------------------------------------------
	NDDAEViewer::NDDAEViewer() :NDCustomModule(ND_CMCBRENDER|ND_CMCBMOUSE|ND_CMCBWIN)
	{
		_g_NDDAEViewerPtr =this;

		this->m_pStrModuleName ="NDDAEViewer";
		m_bUpdateGroupAABB =false;
		m_bMeshInstance =false;
		m_bFinalized =false;

		m_bCHCPPMode =false;
		m_bRENDERBBOX =false;
	}

	//---------------------------------------------------------------------
	//common func.
	bool NDDAEViewer::privateInit()
	{
		return true;
	}

	//---------------------------------------------------------------------
	bool NDDAEViewer::publicInit()
	{
		//CHCMGR
		this->m_pCHCMgrPtr =(NDCHCMgr*)(this->getArk()->queryModule("NDCHCMgr", this));
		m_nCHCID =this->m_pCHCMgrPtr->addCHC();

		//AMELIA
		m_pA =new NDAmelia(this->getArk());
		m_pA->initialize();

		m_nGID =m_pA->newAmeliaGroup("new");


		//MESSAGES
		this->m_nNumHierarchyNodes =NDFONT->addString(L"Arial", FW_NORMAL, 9, L"m_nNumHierarchyNodes");
		NDFONT->SetupStringColor(this->m_nNumHierarchyNodes, NDCOLOR(0,0,0,0));
		this->m_nNumTraversedNodes =NDFONT->addString(L"Arial", FW_NORMAL, 9, L"m_nNumTraversedNodes");
		NDFONT->SetupStringColor(this->m_nNumTraversedNodes, NDCOLOR(0,0,0,0));
		this->m_nNumQueryCulledNodes =NDFONT->addString(L"Arial", FW_NORMAL, 9, L"m_nNumQueryCulledNodes");
		NDFONT->SetupStringColor(this->m_nNumQueryCulledNodes, NDCOLOR(0,0,0,0));
		this->m_nNumFrustumCulledNodes =NDFONT->addString(L"Arial", FW_NORMAL, 9, L"m_nNUMFrustumCulledNodes");
		NDFONT->SetupStringColor(this->m_nNumFrustumCulledNodes, NDCOLOR(0,0,0,0));
		this->m_nNumRenderedGeometry =NDFONT->addString(L"Arial", FW_NORMAL, 9, L"m_nNumRenderedGeometry");
		NDFONT->SetupStringColor(this->m_nNumRenderedGeometry, NDCOLOR(0,0,0,0));

		this->m_pMD =new NDMenuDialog( this->getArk() );
		this->m_pMD->initialize();
		this->m_pMD->setCallbackFunc( modeChangeEvent, buttonPressedEvent );

		m_pLS =new NDLoadingScreen(this->getArk());
		m_pLS->initialize();

		m_pMFVC =new NDMFVCTest(this->getArk());
		m_pMFVC->initialize();


		//preload file ??
		if (this->m_strPreLoadFile.size() >0)
		{
			m_pMD->setCurrMode(0);


			m_bUpdateGroupAABB =false;
			m_bMeshInstance =true;
			this->m_bFinalized =false;

			//m_pCHCMgrPtr->delCHC( m_nCHCID );
			//m_nCHCID =m_pCHCMgrPtr->addCHC();

			//m_pA->delAmeliaGroup( this->m_nGID );
			//m_nGID =m_pA->newAmeliaGroup( "new" );

			char* pChar =new char[m_strPreLoadFile.size()+1];
			memset(pChar, 0, sizeof(char)*(m_strPreLoadFile.size()+1));
			memcpy(pChar, m_strPreLoadFile.c_str(), sizeof(char)*m_strPreLoadFile.size());

			m_nDAEID =m_pA->loadDAEFileMT(pChar, m_nGID);

			delete [] pChar;

			m_pLS->beginLoading();
		}

		return true;
	}

	//---------------------------------------------------------------------
	void NDDAEViewer::release()
	{
		m_pMD->release();
		delete m_pMD;

		m_pLS->release();
		delete m_pLS;

		m_pA->release();
		delete m_pA;

		m_pMFVC->release();
		delete m_pMFVC;

		this->m_bReleased =true;
	}

	//---------------------------------------------------------------------
	//cb func.
	void NDDAEViewer::render(float fElapsedTime)
	{
		static NDOrbitCameraMan* pNDOC =NDCAMERAMAN;

		if (m_bMeshInstance)
		{
			if ( m_pA->isFileLoaded( m_nDAEID ) && (m_bUpdateGroupAABB ==false))
			{
				m_pA->updateGroupAABB( m_nGID );

				//GENERATE CHC TREE
				std::vector< void* > arrMeshInstancePtr;
				m_pA->getAmeliaMeshInstanceListFromGroup( m_nGID, arrMeshInstancePtr );

				NDVECTOR3 vT;
				NDVECTOR3 vS;

				m_pA->getGlobalTranslation( m_nGID, vT );
				m_pA->getGlobalScaling( m_nGID, vS );

				for (int i=0;i<arrMeshInstancePtr.size();++i)
				{
					NDAmeliaMeshForCHC* pNDAMFC =new NDAmeliaMeshForCHC( this->getArk(), m_pA, arrMeshInstancePtr[i], vS, vT );
					this->m_pCHCMgrPtr->addGeometryIntoCHC( this->m_nCHCID, this->m_pCHCMgrPtr->addCustomGeometry( pNDAMFC ) );
				}
				this->m_pCHCMgrPtr->finilizeCHCMT( this->m_nCHCID );
				//this->m_pCHCMgrPtr->setRenderBoundingVolume( this->m_nCHCID, true );

				m_bUpdateGroupAABB =true;
				//m_pLS->endLoading();
			}

			//bool m_bFinalized =false;
			if (!m_bFinalized && this->m_pCHCMgrPtr->bIsFinilized( this->m_nCHCID ))
			{
				m_pLS->endLoading();
				m_pMD->setCurrMode(1);
				m_bFinalized =true;
			}
		
			if (this->m_pCHCMgrPtr->bIsFinilized( this->m_nCHCID ))
			{
				if (this->m_pMD->getCurrMode()==1)
				{
					if (m_bCHCPPMode ==false)
					{
					//AMELIA
						m_pA->renderAmeliaGroup( m_nGID, fElapsedTime, 0.0F );
						if (m_bRENDERBBOX)
							m_pA->renderBBOXInfo( m_nGID );

					}else
					{

						//CHC
						this->m_pCHCMgrPtr->setViewpoint( m_nCHCID, pNDOC->getCurrCameraPtr()->GetEyePt());

						NDVECTOR4 vEQ[6];
						pNDOC->getCurrCameraPtr()->GetFrustumEq( vEQ );
						this->m_pCHCMgrPtr->setFrustumEq( m_nCHCID, vEQ );
						this->m_pCHCMgrPtr->render( m_nCHCID, fElapsedTime, RENDER_ADVANCED_COHERENT );
					}
				}


			}



		}

		if (this->m_pMD->getCurrMode()==2)
		{
			if (this->m_pMFVC->beginRender(fElapsedTime))
			{
				if (m_bCHCPPMode ==false)
				{
				//AMELIA
					NDVECTOR3 vT;
					NDVECTOR3 vS;
					m_pA->getGlobalTranslation( m_nGID, vT );
					m_pA->getGlobalScaling( m_nGID, vS );
					glTranslatef(0.0f, -vT.y*vS.y, 0.0f);
					m_pA->renderAmeliaGroup( m_nGID, fElapsedTime, 0.0F );

					if (m_bRENDERBBOX)
						m_pA->renderBBOXInfo( m_nGID );

					glTranslatef(0.0f, +vT.y*vS.y, 0.0f);

				}else
				{

					//CHC
					this->m_pCHCMgrPtr->setViewpoint( m_nCHCID, pNDOC->getCurrCameraPtr()->GetEyePt());

					NDVECTOR4 vEQ[6];
					pNDOC->getCurrCameraPtr()->GetFrustumEq( vEQ );
					this->m_pCHCMgrPtr->setFrustumEq( m_nCHCID, vEQ );
					this->m_pCHCMgrPtr->render( m_nCHCID, fElapsedTime, RENDER_ADVANCED_COHERENT );
				}
			}
			
			this->m_pMFVC->endRender();
		}

		m_pMD->render( fElapsedTime );
		m_pLS->render( fElapsedTime );

	}


	//---------------------------------------------------------------------
	void NDDAEViewer::renderUI(float fElapsedTime)
	{
		//Other messages
		static NDOrbitCameraMan* pNDOC =NDCAMERAMAN;
		static NDFont*			 pNDF  =NDFONT;
		static NDOSInterface*	 pNDOS =NDOS;

		static int nH =pNDF->GetStringHeight(pNDOC->getCameraStateDescStr());
		static int nW =10;

		//RENDER CAMERA INFO
		pNDF->drawString(nW, pNDOS->getWindowHeight()-nH-5, pNDOC->getCameraStateDescStr(), fElapsedTime);
		//NDGLFILM->renderFilmDesc(fElapsedTime, NDVECTOR2(10.0f, (float)(pNDOS->getWindowHeight()-nH-5-nH) ));

		//OTHER MESSAGE
		static NDHDInfo* pNI =((NDHDInfo*)this->getArk()->queryModule("NDHDInfo", this));
		pNI->render(fElapsedTime);


		//hud info.
		//int nW =10;
		int nH2 =NDW32OS->getWindowHeight()-100;
		WCHAR tmpChar[512] ={0};
		StringCchPrintf( tmpChar, 512, L"m_nNumHierarchyNodes =%d", m_pCHCMgrPtr->getNumHierarchyNodes( m_nCHCID ) );
		pNDF->resetString(&m_nNumHierarchyNodes, tmpChar, L"Arial", FW_NORMAL, 8);
		pNDF->drawString(nW, nH2, this->m_nNumHierarchyNodes, fElapsedTime);
		nH2+=pNDF->GetStringHeight( this->m_nNumHierarchyNodes );
		nH2+=1;

		StringCchPrintf( tmpChar, 512, L"m_nNumTraversedNodes =%d", m_pCHCMgrPtr->getNumTraversedNodes( m_nCHCID ) );
		pNDF->resetString(&m_nNumTraversedNodes, tmpChar, L"Arial", FW_NORMAL, 8);
		pNDF->drawString(nW, nH2, this->m_nNumTraversedNodes, fElapsedTime);
		nH2+=pNDF->GetStringHeight( this->m_nNumTraversedNodes );
		nH2+=1;
		
		StringCchPrintf( tmpChar, 512, L"m_nNumQueryCulledNodes =%d", m_pCHCMgrPtr->getNumQueryCulledNodes( m_nCHCID ) );
		pNDF->resetString(&m_nNumQueryCulledNodes, tmpChar, L"Arial", FW_NORMAL, 8);
		pNDF->drawString(nW, nH2, this->m_nNumQueryCulledNodes, fElapsedTime);
		nH2+=pNDF->GetStringHeight( this->m_nNumQueryCulledNodes );
		nH2+=1;

		StringCchPrintf( tmpChar, 512, L"m_nNumFrustumCulledNodes =%d", m_pCHCMgrPtr->getNumFrustumCulledNodes( m_nCHCID ) );
		pNDF->resetString(&m_nNumFrustumCulledNodes, tmpChar, L"Arial", FW_NORMAL, 8);
		pNDF->drawString(nW, nH2, this->m_nNumFrustumCulledNodes, fElapsedTime);
		nH2+=pNDF->GetStringHeight( this->m_nNumFrustumCulledNodes );
		nH2+=1;

		StringCchPrintf( tmpChar, 512, L"m_nNumRenderedGeometry =%d", m_pCHCMgrPtr->getNumRenderedGeometry( m_nCHCID ) );
		pNDF->resetString(&m_nNumRenderedGeometry, tmpChar, L"Arial", FW_NORMAL, 8);
		pNDF->drawString(nW, nH2, this->m_nNumRenderedGeometry, fElapsedTime);
		nH2+=pNDF->GetStringHeight( this->m_nNumRenderedGeometry );

		if (this->m_pMD->getCurrMode()==2)
		{
			this->m_pMFVC->renderUI(fElapsedTime);
			this->m_pMFVC->frameMove(fElapsedTime);
		}
	}

	long NDDAEViewer::windowMessageProc(bool bMaximumWin, bool bMinimumWin, bool bRestoreWin, bool bSizeChanged)
	{
		if (bSizeChanged | bMaximumWin | bRestoreWin )
		{
			UINT nW =NDW32OS->getWindowWidth();
			UINT nH =NDW32OS->getWindowHeight();

			this->m_pMD->setWindowSz( nW, nH );
			this->m_pLS->setWindowSz( nW, nH );
		}

		return 0;
	}

	//---------------------------------------------------------------------
	long NDDAEViewer::mouseMessageProc(bool bLButtonDown, bool bRButtonDown, bool bMButtonDown, int nWheelDelta, int xPos, int yPos)
	{
		this->m_pMD->mouseMove( xPos, yPos );

		static bool sLBState =false;
		static bool sRBState =false;

		if (sLBState !=bLButtonDown)
		{
			sLBState =bLButtonDown;
			
			if (sLBState)
				m_pMD->mouseLButtonDown();
			else
				m_pMD->mouseLButtonUp();
		}

		if (sRBState !=bRButtonDown)
		{
			sRBState =bRButtonDown;

			if (sRBState)
				m_pMD->mouseRButtonDown();
			else
				m_pMD->mouseRButtonUp();
		}

		//static bool sbLButtonDown =false;
		//if ((bLButtonDown ==true) && (sbLButtonDown ==false))
		//{
		//	sbLButtonDown =true;
		//}

		//if ((bLButtonDown ==false) && (sbLButtonDown ==true))
		//{
		//	sbLButtonDown =false;
		//	this->m_pMD->mouseLButtonClick();
		//}

		//static bool sbRButtonDown =false;
		//if ((bRButtonDown ==true) && (sbRButtonDown ==false))
		//{
		//	sbRButtonDown =true;
		//}

		//if ((bRButtonDown ==false) && (sbRButtonDown ==true))
		//{
		//	sbRButtonDown =false;
		//	this->m_pMD->mouseRButtonClick();
		//}


		return S_OK;
	}

	//---------------------------------------------------------------------
	void NDDAEViewer::buttonPressedEvent( int nButtonID )
	{
		if (_g_NDDAEViewerPtr ==0)
			return;

		_g_NDDAEViewerPtr->internalButtonPressedEvent( nButtonID );
	}

	//---------------------------------------------------------------------
	void NDDAEViewer::modeChangeEvent( int nMode )
	{
		if ( _g_NDDAEViewerPtr ==0)
			return;

		_g_NDDAEViewerPtr->internalModeChangeEvent( nMode );
	}

	//---------------------------------------------------------------------
	void NDDAEViewer::internalButtonPressedEvent( int nButtonID )
	{
		if (this->m_pMD->getCurrMode()==1)
		{
			//normal
			switch(nButtonID)
			{
			case 0:
				{
					//open file
					this->loadFile();

				}
				break;

			case 1:
				{
					//BOUNDING BOX
					//this->saveAsFile();
					m_bRENDERBBOX =!m_bRENDERBBOX;

				}
				break;

			case 2:
				{
					//USING CHC
					m_bCHCPPMode =!m_bCHCPPMode;
				};
				break;

			case 3:
				{
					//toggle mode
					this->toggleState();

				}
				break;

			//case 4:
			//	{
			//		//help
			//		this->help();

			//	}
			//	break;
			}
		}

		if (this->m_pMD->getCurrMode()==2)
		{
			//ar
			switch(nButtonID)
			{
			case 0:
				{
					//toggle mode
					this->toggleState();
				}
				break;

			}
		}
	}

	//---------------------------------------------------------------------
	void NDDAEViewer::internalModeChangeEvent( int nMode )
	{
	}

	//---------------------------------------------------------------------
	void NDDAEViewer::toggleState()
	{
		//...
		if (this->m_pMD->getCurrMode() ==1)
			this->m_pMD->setCurrMode(2);
		else
			this->m_pMD->setCurrMode(1);

	}

	//---------------------------------------------------------------------
	void NDDAEViewer::loadFile()
	{


		wchar_t Filestring[MAX_PATH];
		//C_mystring* returnstring = NULL;

		OPENFILENAME opf;
		opf.hwndOwner = 0;
		opf.lpstrFilter = L"All files\0\*.*\0\0";
		opf.lpstrCustomFilter = 0;
		opf.nMaxCustFilter = 0L;
		opf.nFilterIndex = 1L;
		opf.lpstrFile = Filestring;
		opf.lpstrFile[0] = '\0';
		opf.nMaxFile = 256;
		opf.lpstrFileTitle = 0;
		opf.nMaxFileTitle=50;
		opf.lpstrInitialDir = 0;
		opf.lpstrTitle = L"Open File";
		opf.nFileOffset = 0;
		opf.nFileExtension = 0;
		opf.lpstrDefExt = L"*.*";
		opf.lpfnHook = NULL;
		opf.lCustData = 0;
		opf.Flags = (OFN_PATHMUSTEXIST | OFN_OVERWRITEPROMPT) & ~OFN_ALLOWMULTISELECT;
		opf.lStructSize = sizeof(OPENFILENAME);

		m_pMD->setCurrMode(0);
		if(GetOpenFileName(&opf))
		{
			char pMBStr[1024];
			memset( pMBStr, 0, sizeof(char)*1024);
			WideCharToMultiByte(CP_ACP, 0, opf.lpstrFile, -1, pMBStr, 1024, 0, 0);
			//std::string strOut =pMBStr;

			m_bUpdateGroupAABB =false;
			m_bMeshInstance =true;
			this->m_bFinalized =false;

			m_pCHCMgrPtr->delCHC( m_nCHCID );
			m_nCHCID =m_pCHCMgrPtr->addCHC();

			m_pA->delAmeliaGroup( this->m_nGID );
			m_nGID =m_pA->newAmeliaGroup( "new" );

			m_nDAEID =m_pA->loadDAEFileMT(pMBStr, m_nGID);

			m_pLS->beginLoading();
			
		}else
		{
			m_pMD->setCurrMode(1);
		}

		//m_nDAEID =m_pA->loadDAEFileMT("collada/a_feminine_room/models/a_feminine_room.dae", m_nGID);
		//m_nDAEID =m_pA->loadDAEFileMT("collada/titanic/models/Titanic.dae", m_nGID);
		//m_nDAEID =m_pA->loadDAEFile("collada/Simple_modern_lounge/models/Simple_modern_lounge[1].dae", m_nGID);
		//m_nDAEID =m_pA->loadDAEFile("collada/salon/models/salon.dae", m_nGID);
		//m_nDAEID =m_pA->loadDAEFile("collada/one_for_the_chocoholics/models/one_for_the_chocoholics.dae", m_nGID );
		//m_nDAEID =m_pA->loadDAEFile("collada/Living_For_Two/models/Living_For_Two.dae", m_nGID );
		//m_nDAEID =m_pA->loadDAEFile("collada/Closet_And_Lounge/models/Closet_And_Lounge.dae", m_nGID );


		//m_pLS->beginLoading();
		//m_pMD->setCurrMode(0);
	}

	//---------------------------------------------------------------------
	void NDDAEViewer::preloadFile(std::string& strFilePath)
	{
		if (strFilePath.size()==0)
			return;

		m_strPreLoadFile =strFilePath;


	}


}